package LearnReflection;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ReflectExercise {

	@SuppressWarnings("unused")
	public static void main(String[] args) {

		People people = new People();
		Chinese chinese = new Chinese("楼宗", 21);
		Japanese japanese = new Japanese("Yui Aragaki", 26);
		Class<?> classType = japanese.getClass();
		// task8(chinese);

		reflectPeople("LearnReflection.Japanese", "楼宗", 21);
		System.out.println("======================");
		reflectPeople("LearnReflection.Chinese", "楼宗", 21);
		System.out.println("======================");
		reflectPeople("LearnReflection.People", "楼宗", 21);
		System.out.println("======================");
		reflectPeople("LearnReflection.Aragaki", "楼宗", 21);
	}

	@SuppressWarnings("unused")
	public static void task1(Object obj) {
		// 三种方式获得Person的Class对象
		Class<? extends Object> classType1 = obj.getClass();
		Class<People> classType2 = People.class;
		try {
			Class<?> classType3 = Class.forName("People");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println("这个类是:" + classType1.getName());
	}

	public static void task2(Object obj) {
		// 三种方式创建People的实例
		Class<? extends Object> classType = obj.getClass();
		try {
			Object object = classType.newInstance();//参数
			if (object instanceof People) {
				People people = (People) object;
				people.voice();
			} else if (object instanceof Chinese) {
				Chinese chinese = (Chinese) object;
				chinese.voice();
			} else if (object instanceof Japanese) {
				Japanese japanese = (Japanese) object;
				japanese.voice();
				
			}

		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		try {
			classType.getConstructors()[0].newInstance("this is a people", 10);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

	public static void task3(Object obj) {
		// 调用get set方法
		Class<? extends Object> classType = obj.getClass();
		for (Method m : classType.getMethods()) {
			if ("getName".equals(m.getName())) {
				try {
					System.out.println("getName方法:" + m.invoke(obj));
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if ("setName".equals(m.getName())) {
				try {
					m.invoke(obj, "新垣结衣");
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void task4(Object obj) {
		// 改写属性
		Class<? extends Object> classType = obj.getClass();
		for (Field f : classType.getFields()) {
			if ("name".equals(f.getName())) {
				f.setAccessible(true);
				try {
					f.set(obj, "新垣結衣");
					System.out.println("已改名");
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void task5(Chinese ch) {

		Class<? extends Chinese> classType = ch.getClass();

		Class<People> classType1 = People.class;
		Class<Fightable> classType2 = Fightable.class;

		List<String> list = new ArrayList<>();

		for (Method m : classType1.getMethods()) {
			list.add(m.getName());
		}

		for (Method m : classType2.getMethods()) {
			list.add(m.getName());
		}

		System.out.println("Chinese自定义方法:");
		for (Method m : classType.getDeclaredMethods()) {
			if (!list.contains(m.getName())) {
				System.out.println(m.getName() + "():" + m.getReturnType());
			}
		}
	}

	public static void task6(Chinese ch) {
		// 获取所有公开方法
		Class<? extends Chinese> classType = ch.getClass();
		Method[] pubMethods = classType.getDeclaredMethods();
		System.out.println("公开方法有:");
		for (Method m : pubMethods) {
			System.out.println(m.getName());
		}
	}

	public static void task7(Chinese ch) {
		Class<? extends Chinese> classType = ch.getClass();
		Class<?> father = classType.getSuperclass();
		System.out.println("父类的名字是:" + father.getName());
		System.out.println("父类的属性有:");
		for (Field f : father.getDeclaredFields()) {
			System.out.println(f.getName());
		}
		System.out.println("父类的方法有:");
		for (Method m : father.getDeclaredMethods()) {
			System.out.println(m.getName());
		}
	}

	public static void task8(Chinese ch) {
		Class<? extends Chinese> classType = ch.getClass();

		Class<?>[] interfaces = classType.getInterfaces();
		for (Class<?> inter : interfaces) {
			System.out.println("接口名:" + inter.getName());
			System.out.println("常量:");
			for (Field f : inter.getDeclaredFields()) {
				System.out.println(f.getName());
			}
			System.out.println("方法:");
			for (Method m : inter.getDeclaredMethods()) {
				System.out.println(m.getName());
			}
		}
	}

	public static void reflectPeople(String className, String name, int age) {
		Class<?> classType;
		try {
			// 创建类的实例
			classType = Class.forName(className);
			Object obj = classType.getConstructors()[0].newInstance("louzong", 10);
			if (obj instanceof Chinese) {
				Chinese chinese = new Chinese();
				chinese.voice();
			} else if (obj instanceof Japanese) {
				Japanese japanese = new Japanese();
				japanese.voice();
			} else if (obj instanceof People) {
				People people = new People();
				people.voice();
			}

			// 判断接口
			if (isImplements(classType)) {

				Class<?> inter = Fightable.class;
				Set<String> interfaceMethods = new HashSet<>();
				for (Method m : inter.getMethods()) {
					interfaceMethods.add(m.getName());
				}

				Class<Chinese> sino = Chinese.class;
				for (Method m : sino.getDeclaredMethods()) {
					if (interfaceMethods.contains(m.getName())) {
						m.invoke(obj);
					}
				}
			} else {
				System.out.println("没有实现接口");
			}

			// 判断有无pingpang方法
			boolean hasPingpang = false;
			for (Method m : classType.getDeclaredMethods()) {
				if ("pingpang".equals(m.getName())) {
					m.setAccessible(true);
					m.invoke(obj);
					hasPingpang = true;
				}
			}
			if (!hasPingpang) {
				System.out.println("没有pingpang方法");
			}

			// 判断有无sushi方法
			boolean hasSushi = false;
			for (Method m : classType.getDeclaredMethods()) {
				if ("eatSushi".equals(m.getName())) {
					m.setAccessible(true);
					m.invoke(obj);
					hasSushi = true;
				}
			}
			if (!hasSushi) {
				System.out.println("没有eatSushi方法");
			}
		} catch (ClassNotFoundException e) {
			System.out.println("类名错误");
			// e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}

	}

	public static boolean isImplements(Class<?> classType) {

		Class<?>[] interfaces = classType.getInterfaces();
		for (Class<?> c : interfaces) {
			if ("LearnReflection.Fightable".equals(c.getName())) {
				return true;
			}
		}
		return false;

	}

}
